// Copyright (c) Microsoft Corporation.  All rights reserved.

#include "stdafx.h"

#include "CommonUtils.h"
#include "DWriteFactory.h"
#include "DWriteTextFormat.h"
#include "DWriteTextLayout.h"
#include "DWriteInlineObject.h"
#include "DWriteRenderingParams.h"

using namespace Microsoft::WindowsAPICodePack::DirectX;
using namespace Microsoft::WindowsAPICodePack::DirectX::DirectWrite;

typedef HRESULT (*CreateDWriteFactoryFuncPtr)(DWRITE_FACTORY_TYPE factoryType, REFIID riid, IUnknown **factory);

DWriteFactory^ DWriteFactory::CreateFactory()
{
    wchar_t* libName = L"DWrite.dll";
    HINSTANCE library = CommonUtils::LoadDll(libName);

    CreateDWriteFactoryFuncPtr createFuncPtr = 
        (CreateDWriteFactoryFuncPtr) CommonUtils::GetFunctionfromDll(
            library, "DWriteCreateFactory");

    IDWriteFactory * pNativeIDWriteFactory = NULL;

    CommonUtils::VerifyResult(
        (*createFuncPtr)(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), (IUnknown**)(&pNativeIDWriteFactory)));

    return gcnew DWriteFactory(pNativeIDWriteFactory, library);
}

DWriteFactory^ DWriteFactory::CreateFactory(DWriteFactoryType factoryType)
{
    wchar_t* libName = L"DWrite.dll";
    HINSTANCE library = CommonUtils::LoadDll(libName);

    CreateDWriteFactoryFuncPtr createFuncPtr = 
        (CreateDWriteFactoryFuncPtr) CommonUtils::GetFunctionfromDll(
            library, "DWriteCreateFactory");

    IDWriteFactory * pNativeIDWriteFactory = NULL;

    CommonUtils::VerifyResult(
        (*createFuncPtr)(static_cast<DWRITE_FACTORY_TYPE>(factoryType), __uuidof(IDWriteFactory), (IUnknown**)(&pNativeIDWriteFactory)));

    return gcnew DWriteFactory(pNativeIDWriteFactory, library);
}


TextFormat^ DWriteFactory::CreateTextFormat(
    String^ fontFamilyName,
    Single fontSize,
    FontWeight fontWeight,
    FontStyle fontStyle,
    FontStretch fontStretch,
    String^ localeName)
{
    IDWriteTextFormat * textFormat = NULL;

    marshal_context^ context = gcnew marshal_context();

    CommonUtils::VerifyResult(GetInterface<IDWriteFactory>()->CreateTextFormat(        
        context->marshal_as<const WCHAR *>(fontFamilyName),
         NULL,
         static_cast<DWRITE_FONT_WEIGHT>(fontWeight),
         static_cast<DWRITE_FONT_STYLE>(fontStyle),
         static_cast<DWRITE_FONT_STRETCH>(fontStretch),
         fontSize,
         String::IsNullOrEmpty(localeName) ? L"" : context->marshal_as<const WCHAR *>(localeName),            
         &textFormat));
    
    return textFormat ? gcnew TextFormat(textFormat) : nullptr;
}

TextFormat^ DWriteFactory::CreateTextFormat(
    String^ fontFamilyName,
    Single fontSize,
    FontWeight fontWeight,
    FontStyle fontStyle,
    FontStretch fontStretch)
{
    return CreateTextFormat(fontFamilyName, fontSize, fontWeight, fontStyle, fontStretch, nullptr);
}

TextFormat^ DWriteFactory::CreateTextFormat(
    String^ fontFamilyName,
    Single fontSize)
{
    return CreateTextFormat(fontFamilyName, fontSize, FontWeight::Normal, FontStyle::Normal, FontStretch::Normal, nullptr);
}



RenderingParams^ DWriteFactory::CreateRenderingParams()
{
    IDWriteRenderingParams * renderingParams = NULL;

    CommonUtils::VerifyResult(GetInterface<IDWriteFactory>()->CreateRenderingParams(
        &renderingParams));
    
    return renderingParams ? gcnew RenderingParams(renderingParams) : nullptr;
}

RenderingParams^ DWriteFactory::CreateMonitorRenderingParams(
    IntPtr monitorHandle
    )
{
    IDWriteRenderingParams * renderingParams = NULL;

    CommonUtils::VerifyResult(GetInterface<IDWriteFactory>()->CreateMonitorRenderingParams(
        static_cast<HMONITOR>(monitorHandle.ToPointer()),
        &renderingParams));
    
    return renderingParams ? gcnew RenderingParams(renderingParams) : nullptr;
}

RenderingParams^ DWriteFactory::CreateCustomRenderingParams(
    FLOAT gamma,
    FLOAT enhancedContrast,
    FLOAT clearTypeLevel,
    PixelGeometry pixelGeometry,
    RenderingMode renderingMode)
{
    IDWriteRenderingParams * renderingParams = NULL;

    CommonUtils::VerifyResult(GetInterface<IDWriteFactory>()->CreateCustomRenderingParams(
        gamma,
        enhancedContrast,
        clearTypeLevel,
        static_cast<DWRITE_PIXEL_GEOMETRY>(pixelGeometry),
        static_cast<DWRITE_RENDERING_MODE>(renderingMode),
        &renderingParams));
    
    return renderingParams ? gcnew RenderingParams(renderingParams) : nullptr;
}

TextLayout^ DWriteFactory::CreateTextLayout(
    String^ text,
    TextFormat^ textFormat,
    FLOAT maxWidth,
    FLOAT maxHeight
    )
{
    IDWriteTextLayout* textLayout = NULL;
    marshal_context^ context = gcnew marshal_context();

    CommonUtils::VerifyResult(GetInterface<IDWriteFactory>()->CreateTextLayout(
        context->marshal_as<const WCHAR*>(text), text->Length,textFormat->GetInterface<IDWriteTextFormat>(),
        maxWidth, maxHeight, &textLayout));

    return textLayout ? gcnew TextLayout(textLayout) : nullptr;
}

TextLayout^ DWriteFactory::CreateGdiCompatibleTextLayout(
    String^ text,
    TextFormat^ textFormat,
    FLOAT layoutWidth,
    FLOAT layoutHeight,
    FLOAT pixelsPerDip,
    Boolean useGdiNatural,
    Matrix transform        
    )
{
    IDWriteTextLayout* textLayout = NULL;
    marshal_context^ context = gcnew marshal_context();

    DWRITE_MATRIX matrixCopy;
    transform.CopyTo(&matrixCopy);

    CommonUtils::VerifyResult(GetInterface<IDWriteFactory>()->CreateGdiCompatibleTextLayout(
        context->marshal_as<const WCHAR*>(text), text->Length,textFormat->GetInterface<IDWriteTextFormat>(),
        layoutWidth, layoutHeight, pixelsPerDip, &matrixCopy, useGdiNatural ? TRUE : FALSE, &textLayout));

    return textLayout ? gcnew TextLayout(textLayout) : nullptr;
}

TextLayout^ DWriteFactory::CreateGdiCompatibleTextLayout(
    String^ text,
    TextFormat^ textFormat,
    FLOAT layoutWidth,
    FLOAT layoutHeight,
    FLOAT pixelsPerDip,
    Boolean useGdiNatural
    )
{
    IDWriteTextLayout* textLayout = NULL;
    marshal_context^ context = gcnew marshal_context();

    CommonUtils::VerifyResult(GetInterface<IDWriteFactory>()->CreateGdiCompatibleTextLayout(
        context->marshal_as<const WCHAR*>(text), text->Length,textFormat->GetInterface<IDWriteTextFormat>(),
        layoutWidth, layoutHeight, pixelsPerDip, NULL, useGdiNatural, &textLayout));

    return textLayout ? gcnew TextLayout(textLayout) : nullptr;
}

InlineObject^ DWriteFactory::CreateEllipsisTrimmingSign(
    TextFormat^ textFormat
    )
{
    IDWriteInlineObject* inlineObject = NULL;

    CommonUtils::VerifyResult(GetInterface<IDWriteFactory>()->CreateEllipsisTrimmingSign(
        textFormat->GetInterface<IDWriteTextFormat>(),
        &inlineObject));

    return inlineObject ? gcnew InlineObject(inlineObject) : nullptr;
}
